﻿using DongFangGuoKai.TaskPlatform.Commn.ApiModule.Dto;
using DongFangGuoKai.TaskPlatform.Commn.ApiModule.Model;
using DongFangGuoKai.TaskPlatform.Commn.ConfigureOptions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using RestSharp;
using System.Diagnostics;
using System.Text;
using System.Text.Unicode;

namespace DongFangGuoKai.TaskPlatform.Commn.ApiModule
{
    /// <summary>
    /// Http请求帮助类
    /// </summary>
    public class ApiClient : IApiClient
    {
        private readonly RestClient _client;
        private readonly IMemoryCache _cache;
        private readonly TokenConfigOption _tokenConfigOption;
        public ApiClient(RestClient client, IMemoryCache cache, IOptions<TokenConfigOption> option)
        {
            _client = client;
            _cache = cache;
            _tokenConfigOption = option.Value;
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <typeparam name="T">返回消息体</typeparam>
        /// <param name="resource">url</param>
        /// <param name="data">请求body</param>
        /// <param name="headers">请求头</param>
        /// <returns></returns>
        public T Post<T>(string resource, object data, Dictionary<string, string> headers = default) where T : new()
        {
            var request = new RestRequest(resource, Method.Post);

            if (data != null)
            {
                request.AddJsonBody(data);
            }

            if (headers != null)
            {
                foreach (var header in headers)
                {
                    request.AddHeader(header.Key, header.Value);
                }
            }

            return Execute<T>(request);
        }
        public T Post<T>(string resource, object data) where T : new()
        {
            return Post<T>(resource, data, default);
        }
        public T Post<T>(string resource) where T : new()
        {
            return Post<T>(resource, null, null);
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <typeparam name="T">返回消息体</typeparam>
        /// <param name="resource">url</param>
        /// <param name="headers">请求头</param>
        /// <param name="parameter">请求参数</param>
        /// <returns></returns>
        public T Get<T>(string resource, Parameter[] parameter, Dictionary<string, string> headers = default) where T : new()
        {

            var request = new RestRequest(resource, Method.Get)
             ;
            if (headers != null)
            {
                foreach (var header in headers)
                {
                    request.AddHeader(header.Key, header.Value);
                }
            }

            if (parameter != null && parameter.Length > 0)
            {
                foreach (var item in parameter)
                {
                    request.AddParameter(item);
                }
            }


            return Execute<T>(request);

        }
        public T Get<T>(string resource, Parameter[] parameter) where T : new()
        {
            return Get<T>(resource, parameter, default);
        }
        public T Get<T>(string resource) where T : new()
        {
            return Get<T>(resource, default, default);
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <typeparam name="T">返回 T </typeparam>
        /// <param name="resource">url</param>
        /// <param name="headers">请求头</param>
        /// <param name="parameter">请求参数</param>
        /// <returns></returns>
        public T Put<T>(string resource, Parameter[] parameter, Dictionary<string, string> headers = default) where T : new()
        {
            var request = new RestRequest(resource, Method.Put);
            if (headers != null)
            {
                foreach (var header in headers)
                {
                    request.AddHeader(header.Key, header.Value);
                }
            }

            if (parameter != null && parameter.Length > 0)
            {
                foreach (var item in parameter)
                {
                    request.AddParameter(item);
                }
            }

            return Execute<T>(request);
        }
        public T Put<T>(string resource, Parameter[] parameter) where T : new()
        {
            return Put<T>(resource, parameter, null);
        }
        public T Put<T>(string resource) where T : new()
        {
            return Put<T>(resource, null, null);
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <returns></returns>
        /// <exception cref="RestSharpException"></exception>
        private T Execute<T>(RestRequest request) where T : new()
        {
            if (request.Resource.StartsWith(_tokenConfigOption.Url))
            {
                string authToken = GetAuthToken();

                request.AddHeader("Authorization", $"Bearer {authToken}");
            }           

            var response = _client.Execute(request);
            if (response.IsSuccessful)
            {
                return JsonConvert.DeserializeObject<T>(response.Content);
            }
            string errMsg = $"[请求Url：{request.Resource}] \n[请求参数：{JsonConvert.SerializeObject(response.Request.Parameters?.FirstOrDefault()?.Value)}] \n[详细信息：{response.Content}] \n [状态码：{response.StatusCode}]\n ";
            throw new RestSharpException(response.StatusCode, errMsg);
        }

        /// <summary>
        /// 获取Token
        /// </summary>
        /// <returns></returns>
        public string GetAuthToken()
        {
            string? token = _cache.Get<string>(_tokenConfigOption.Key);

            if (string.IsNullOrEmpty(token))
            {
                //生成请求实体
                #region 生成获取Token请求对象
                //获取私钥
                string privateSecret = _tokenConfigOption.Secret;
                //获取当前时间戳
                long unixTimestamp = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                //获取随机数
                int random = new Random().Next(1, 9999);
                //拼接字符串
                string originStr = privateSecret + unixTimestamp.ToString() + random;
                //SHA1加密
                string originResult = SH1Helper.ComputeSHA1(originStr);
                TokenDto tokenRequest = new TokenDto()
                {
                    Random = random,
                    Secret = originResult,
                    Tenantid = "cosmic",
                    Timestamp = unixTimestamp,
                    User = _tokenConfigOption.UserPhone
                };
                #endregion


                #region 发送请求 
                string url = _tokenConfigOption.Url + "railway/async/getToken";
                var request = new RestRequest(url, Method.Post);
                request.AddJsonBody(tokenRequest, ContentType.Json);

                ApiResultData result;
                var response = _client.Execute(request);
                if (response.IsSuccessful)
                {
                    result = JsonConvert.DeserializeObject<ApiResultData>(response.Content);
                    if (result.Data != null && result.Code == "200")
                    {
                        #region 解析响应实体，缓存Token字符串，有效期提前一分钟
                        //解析详细实体
                        TokenResponsModel? tokenRespons = result.Data.ToObject<TokenResponsModel>();
                        //有效期进行毫秒转换DateTimeOffset
                        var timeOffset = SH1Helper.FromUnixTimeMilliseconds(tokenRespons.ExpireTime);
                        var time = timeOffset.DateTime;

                        //缓存Token
                        _cache.Set<string>(_tokenConfigOption.Key, tokenRespons.Token, timeOffset);
                        return tokenRespons.Token;
                        #endregion
                    }
                    return "";
                }

                string tokenErr = $"[请求Url：{_tokenConfigOption.Url + "railway/async/getToken"}] \n[请求参数：{JsonConvert.SerializeObject(tokenRequest)}] \n [错误信息：{response.ErrorMessage}][详细信息：{response.Content}]";
                throw new Exception(tokenErr);
                #endregion  

            }

            return token;

        }

    }
    public class RestSharpException : Exception
    {
        public RestSharpException(System.Net.HttpStatusCode statusCode, string errorMessage) : base(errorMessage)
        {
            StatusCode = statusCode;
        }

        public System.Net.HttpStatusCode StatusCode { get; }
    }

}
